package com.ytkj.digitalConstruction.service.dept;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.ytkj.digitalConstruction.dao.dept.DeptMapper;
import com.ytkj.digitalConstruction.dao.dept.DeptProjectMapper;
import com.ytkj.digitalConstruction.dao.dept.DeptUserMapper;
import com.ytkj.digitalConstruction.dao.user.UserMapper;
import com.ytkj.digitalConstruction.entity.dept.Dept;
import com.ytkj.digitalConstruction.entity.dept.DeptUser;
import com.ytkj.digitalConstruction.entity.role.Role;
import com.ytkj.digitalConstruction.entity.user.User;
import com.ytkj.digitalConstruction.enums.dept.DeptTypeEnum;
import com.ytkj.digitalConstruction.enums.ding.DingOperationEnum;
import com.ytkj.digitalConstruction.httpbean.PageResult;
import com.ytkj.digitalConstruction.httpbean.dept.ResDept;
import com.ytkj.digitalConstruction.httpbean.dept.req.AddOrUpdateDingDept;
import com.ytkj.digitalConstruction.httpbean.dept.req.PageDept;
import com.ytkj.digitalConstruction.httpbean.dept.req.ReqDept;
import com.ytkj.digitalConstruction.httpbean.dept.req.ReqDingDept;
import com.ytkj.digitalConstruction.httpbean.user.resbean.UserRoleBean;
import com.ytkj.digitalConstruction.rabbit.BaseVar;
import com.ytkj.digitalConstruction.rabbit.Sender;
import com.ytkj.digitalConstruction.service.role.RoleService;

/**
 * 部门业务处理类
 * 
 * @author Pete
 * @Date 2017年12月7日
 */
@Service
@Transactional
public class DeptService {

	@Autowired
	private DeptMapper deptMapper;

	@Autowired
	private UserMapper userMapper;
	
	@Autowired
	private DeptUserMapper deptUserMapper;

	@Autowired
	private RoleService roleService;
	@Autowired
	private Sender sender;
	@Autowired
	private BaseVar baseVar;
	@Autowired
	private DeptProjectMapper deptProjectMapper;

	Logger log = LoggerFactory.getLogger(getClass());

	/**
	 * 增加部门
	 * 
	 * @param reqDept
	 * @return 成功时，返回空字符串，失败时，返回错误信息
	 */
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public String addDept(ReqDept reqDept) {

		// 向数据库中新增部门
		Dept dept = reqDept.dept();
		if (deptMapper.insertSelective(dept) < 1) {
			log.error("DeptService addDept Exception: deptMapper.insertSelective faild!");
			return "向数据库添加失败！";
		}
		reqDept.setDeptId(dept.getDeptId());
		// 向钉钉中添加部门
		String dingMsg = addOrUpdateToDing(dept, DingOperationEnum.CREATE.getValue());
		if (!StringUtils.isEmpty(dingMsg)) {
			log.error("DeptService addDept Exception: add to Ding faild!");
			return dingMsg;
		}
		return "";
	}

	/**
	 * 向钉钉中添加或修改部门
	 *
	 * @param addedDept
	 * @param type
	 * @return
	 */
	private String addOrUpdateToDing(Dept addedDept, String type) {
		AddOrUpdateDingDept dept = addOrUpdateDingDept(addedDept, type);
		String msg = JSONObject.toJSONString(dept);
		String response = sender.send(msg, baseVar.getRoutingkeyDepartment());
		if (JSONObject.parseObject(response).getBooleanValue("success") == false) {
			log.error("DeptSerice addOrUpdateToDing Exception: 钉钉执行操作失败!");
			//throw new CustomException(DingExceptionEnum.ADD_OR_UPDATE_ERROR);
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return "钉钉消息：" + JSONObject.parseObject(response).getString("msg");
		}
		return "";

	}

	/**
	 * 获取向钉钉添加时候的Dept对象
	 * 
	 * @param addedDept
	 * @param type
	 * @return
	 */
	private AddOrUpdateDingDept addOrUpdateDingDept(Dept addedDept, String type) {
		AddOrUpdateDingDept dept = new AddOrUpdateDingDept();
		dept.setType(type);

		ReqDingDept reqDingDept = new ReqDingDept();
		reqDingDept.setId(addedDept.getDeptId());
		reqDingDept.setName(addedDept.getDeptName());
		reqDingDept.setParentid(addedDept.getParentId());
		reqDingDept.setOrder(addedDept.getDeptOrder());

		dept.setDept(reqDingDept);
		return dept;
	}

	/**
	 * 删除部门
	 * 
	 * @param deptId
	 * @return
	 */
	public boolean deleteDept(Integer deptId) {
		// 删除数据库中的数据
		if (deptMapper.deleteByPrimaryKey(deptId) < 1) {
			log.error("DeptSerice deleteDept Exception: deptMapper.deleteByPrimaryKey faild!");
			return false;
		}
		// 删除钉钉中的数据
		AddOrUpdateDingDept dept = new AddOrUpdateDingDept();
		dept.setType(DingOperationEnum.DELETE.getValue());
		ReqDingDept reqDingDept = new ReqDingDept();
		reqDingDept.setId(deptId);
		dept.setDept(reqDingDept);
		
		String msg = JSONObject.toJSONString(dept);
		String response = sender.send(msg, baseVar.getRoutingkeyDepartment());
		if (JSONObject.parseObject(response).getBooleanValue("success") == false) {
			log.error("DeptSerice deleteDept Exception:从钉钉删除失败!");
			//throw new CustomException(DingExceptionEnum.DELETE_ERROR);
		}
		return true;
	}

	/**
	 * 修改部门
	 * 
	 * @param reqDept
	 * @return 修改成功时，返回空字符串，修改失败时，返回失败信息
	 */
	public String updateDept(ReqDept reqDept) {
		Dept dept = reqDept.dept();
		if(deptMapper.selectByPrimaryKey(dept.getDeptId()) == null) {
			return "要操作的数据不存在";
		}
		// 修改数据库的记录
		if (deptMapper.updateByPrimaryKeySelective(reqDept.dept())< 1) {
			log.error("DeptService updateDept Exception: updateByPrimaryKey faild!");
			return "数据库修改失败";
		}
		// 修改钉钉上的部门信息
		String dingMsg = addOrUpdateToDing(dept, DingOperationEnum.UPDATE.getValue());
		if (!StringUtils.isEmpty(dingMsg)) {
			log.error("DeptService updateDept Exception: addOrUpdateToDing faild!");
			return dingMsg;
		}
		return "";
	}

	/**
	 * 以当前部门为跟节点，获取部门树状结构
	 * 
	 * @param deptId
	 * @return
	 */
	public Map<String, Object> getDeptTree(int deptId) {
		Map<String, Object> map = new HashMap<>();
		Dept dept = deptMapper.selectByPrimaryKey(deptId);
		if(dept == null) {
			return Collections.emptyMap();
		}
		map.put("deptId", dept.getDeptId());
		map.put("id", dept.getDeptId());
		map.put("deptOrder", dept.getDeptOrder());
		map.put("deptType", dept.getDeptType());
		map.put("deptDesc", dept.getDeptDesc());
		map.put("parentIds", findAncestors(dept.getParentId()));
		String deptName =  dept.getDeptType().equals(DeptTypeEnum.DEPT.getValue())?dept.getDeptName():(dept.getDeptName() + "(虚拟)"); 
		map.put("deptName", deptName);
		List<Dept> children = deptMapper.selectChildren(deptId);
		if (children != null && children.size() > 0) {
			List<Map<String, Object>> list = new ArrayList<>();
			for (Dept d : children) {
				list.add(getDeptTree(d.getDeptId()));
			}
			map.put("children", list);
		}
		return map;
	}
	
	/**
	 * @param deptId
	 * @return
	 */
	public Map<String, Object> getrealDeptTree(int deptId) {
		Map<String, Object> map = new HashMap<>();
		Dept dept = deptMapper.selectByPrimaryKey(deptId);
		if(dept == null) {
			throw new NullPointerException();
		}
		map.put("deptId", dept.getDeptId());
		map.put("id", dept.getDeptId());
		map.put("deptOrder", dept.getDeptOrder());
		map.put("deptType", dept.getDeptType());
		map.put("deptDesc", dept.getDeptDesc());
		map.put("parentIds", findAncestors(dept.getParentId()));
		String deptName =  dept.getDeptType().equals(DeptTypeEnum.DEPT.getValue())?dept.getDeptName():(dept.getDeptName() + "(虚拟)"); 
		map.put("deptName", deptName);
		List<Dept> children = deptMapper.selectByParentIdAndType(deptId,DeptTypeEnum.DEPT.getValue());
		if (children != null && children.size() > 0) {
			List<Map<String, Object>> list = new ArrayList<>();
			for (Dept d : children) {
				list.add(getrealDeptTree(d.getDeptId()));
			}
			map.put("children", list);
		}
		return map;
	}

	/**
	 * 将部门Map树转换成POJO
	 * 
	 * @param parentIds
	 * @param mapList
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<ResDept> deptTree(int[] parentIds, List<Map<String, Object>> mapList) {
		List<ResDept> resList = new ArrayList<>();
		if (parentIds == null) {
			// 默认根节点
			parentIds = new int[] { 0 };
		}
		ResDept resDept;
		for (Map<String, Object> map : mapList) {
			resDept = new ResDept();
			int deptId = Integer.parseInt(map.get("deptId").toString());
			resDept.setDeptId(deptId);
			resDept.setId(Integer.parseInt(map.get("deptId").toString()));
			resDept.setDeptName(map.get("deptName").toString());
			resDept.setDeptOrder(Integer.parseInt(map.get("deptOrder").toString()));
			resDept.setDeptType(Integer.parseInt(map.get("deptType").toString()));
			resDept.setDeptDesc(map.get("deptDesc").toString());
			resDept.setParentIds(parentIds);
			List<Map<String, Object>> children = (List<Map<String, Object>>) map.get("children");
			if (children != null && children.size() > 0) {
				int len = parentIds.length + 1;
				int[] newParents = new int[len];
				for (int i = 0; i < len; i++) {
					if (i == len - 1) {
						newParents[i] = deptId;
					} else {
						newParents[i] = parentIds[i];
					}
				}
				resDept.setChildren(deptTree(newParents, children));
			}
			resList.add(resDept);
		}
		return resList;
	}

	/**
	 * 获取部门所有用户
	 * 
	 * @param pageDept
	 * @return
	 */
	public PageResult<UserRoleBean> getUsers(PageDept pageDept) {
		PageHelper.startPage(pageDept.getPageCurrent(), pageDept.getPageSize());
		if(StringUtil.isEmpty(pageDept.getUserName())) {
			pageDept.setUserName(null);
		}
		Page<User> deptUsers = deptUserMapper.selectUserListByDeptId(pageDept.getDeptId(),pageDept.getUserName());

		//若根据用户姓名查询，且查询结果为空是，则递归查询子部门下的员工，直到查询到数据
		if(pageDept.getUserName() != null){

			 deptUsers = recursiveFindUser(pageDept.getDeptId(),pageDept.getUserName(),deptUsers);

			//由于一个用户可能在多个虚拟部门下，所以需要去重
			for(int i = 0; i < deptUsers.size() - 1; i++){
				for(int j = i+1; j < deptUsers.size(); j++){
					if(deptUsers.get(i).getUserId().equals(deptUsers.get(j).getUserId())){
						deptUsers.setTotal(deptUsers.getTotal() - 1);
						deptUsers.remove(j);
						j--;

					}
				}
			}
		}

		List<UserRoleBean> userRoleBeanList = new ArrayList<>();
		for(User user:deptUsers) {
			UserRoleBean userRoleBean = userToUserBean(user);
			//实体部门
			List<Integer> roleIdList = new ArrayList<Integer>();
			//虚拟部门
			List<Integer> virRoleIdList = new ArrayList<Integer>();
			roleIdList.addAll(roleService.getUserRoleIdsByUserId(user.getUserId()));
			virRoleIdList.addAll(roleService.getUserGroupRoleIdsByUserId(user.getUserId()));
			userRoleBean.setRoleIds(roleIdList);
			userRoleBean.setVirRoleIds(virRoleIdList);
			userRoleBeanList.add(userRoleBean);
		}
		
		PageResult<UserRoleBean> pageResult = new PageResult<>();
		// 查询所有未删除消息
		log.info("查询所有消息条数开始");
		pageResult.setItemTotal(deptUsers.getTotal());
		log.info("查询所有消息条数结束");
		pageResult.setItems(userRoleBeanList);
		log.info("查询所有消息成功");
		return pageResult;
	}

	/**
	 * 递归查询子部门下的员工
	 *
	 * @param deptId
	 * @param userName
	 * */
	private Page<User> recursiveFindUser(Integer deptId,String userName,Page<User> resultList) {
		List<Dept> deptList = deptMapper.selectChildren(deptId);
		for(Dept dept : deptList){
			List<User> result = deptUserMapper.selectUserListByDeptId(dept.getDeptId(),userName);
			if(result.size() > 0){
				resultList.addAll(result);
				resultList.setTotal(resultList.getTotal()+result.size());
			}
		}
		return resultList;

	}

	/**
	 * 将User对象转换为User的子类UserBean对象
	 * 
	 * @param user
	 * @return
	 */
	private UserRoleBean userToUserBean(User user) {
		String jsonStr = JSONObject.toJSONString(user);
		return JSONObject.parseObject(jsonStr, UserRoleBean.class);
	}

	/**
	 * 根据项目组ID获取项目组中的所有角色
	 * 
	 * @param deptId
	 * @return
	 */
	public List<Role> getRolesByProjectDeptId(int deptId) {
		Dept dept = deptMapper.selectByPrimaryKey(deptId);
		// 项目组
		if (dept.getDeptType() == 1) {
			return Collections.emptyList();
		}
		List<DeptUser> deptUsers = deptUserMapper.selectByDeptId(deptId);
		Map<Integer, Role> roles = new HashMap<>();
		for (DeptUser du : deptUsers) {
			User user = userMapper.selectByPrimaryKey(du.getUserId());
			List<Role> list = roleService.getUserRoles(user.getUserId());

			for (Role r : list) {
				roles.put(r.getRoleId(), r);
			}
		}
		return roles.values().stream().collect(Collectors.toList());
	}

	public List<Map<String, Object>> getAll() {
		List<Map<String, Object>> list = new ArrayList<>();
		List<Dept> depts = deptMapper.selectAll();
		for (Dept d : depts) {
			Map<String, Object> map = new HashMap<>();
			map.put("name", d.getDeptName());
			map.put("id", d.getDeptId());
			map.put("parentId", d.getParentId());
			map.put("type", d.getDeptType());
			list.add(map);
		}
		return list;
	}

	/**
	 * 测试新加
	 * 
	 * @param deptId
	 * @return
	 */
	/*public Integer deleteByDept(Integer deptId) {
		return deptMapper.deleteByDept(deptId);
	}*/

	public boolean isHaveSubSet(Integer deptId) {
		return deptMapper.selectChildren(deptId).size() > 0;
	}

	public boolean isHaveUser(Integer deptId) {
		List<DeptUser> depts = deptUserMapper.selectByDeptId(deptId);
		//如果人员存在，判断人员是否可用；可用返回false
		List<Integer> userList = new ArrayList<>();
		for(DeptUser deptUser: depts) {
			userList.add(deptUser.getUserId());
		}
		return userMapper.selectByUserIdListAndStatus(userList).size() > 0;
	}

	/**
	 * 根据项目部Id与角色Id列表查询用户列表
	 * @param deptId
	 * @param roleIds
	 * @return
	 */
	public List<Integer> getUserIdListBydeptIdAndRoleId(Integer deptId, List<Integer> roleIds) {
		return deptMapper.selectUserIdListBydeptIdAndRoleId(deptId, roleIds);
	}

	/**
	 * 向上查询指定部门包括本身id 的deptId
	 * 
	 * @param deptId
	 * @return
	 */
	public List<Integer> findAncestors(Integer deptId) {
		List<Integer> deptIds = new ArrayList<>();
		if(deptId == 0) {
			return deptIds;
		}
		deptIds.add(deptId);
		
		while(true) {
			Integer parentId = deptMapper.selectParentId(deptId);
			if(parentId == null) {
				throw new NullPointerException("父部门id不能为null!");
			}
			if(parentId == 0) {
				break;
			}
			deptIds.add(parentId);
			deptId = parentId;		
		}
		Collections.reverse(deptIds);  
		return deptIds;
	}

	/**
	 * 查询某用户所在的虚拟部门id list
	 * 
	 * @param userId
	 * @return
	 */
	public List<Integer> findVirDept(Integer userId) {
		return deptUserMapper.selectDeptIdByUserIdAndDeptType(userId,DeptTypeEnum.VIR_DEPT.getValue());
	}

	/**
	 * @param deptIds
	 * @return
	 */
	public List<Integer> findProjectByDeptIds(List<Integer> deptIds) {
		return deptProjectMapper.selectProjectIdByDeptIds(deptIds);
	}
	/**
	 * 查询部门
	 * @param deptId
	 * @return
	 */
	public Dept selectByDeptId(Integer deptId) {
		return  deptMapper.selectByPrimaryKey(deptId);
		
	}

	/**
	 * @param deptId
	 * @return
	 */
	public List<UserRoleBean> getUsers(Integer deptId) {
		List<User> deptUsers = deptUserMapper.selectUserListByDeptId(deptId,null);
		List<UserRoleBean> userRoleBeanList = new ArrayList<>();
		for(User user:deptUsers) {
			UserRoleBean userRoleBean = userToUserBean(user);
			List<Integer> roleIdList = new ArrayList<>();
			List<Integer> virRoleIdList = new ArrayList<>();
			roleIdList.addAll(roleService.getUserRoleIdsByUserId(user.getUserId()));
			virRoleIdList.addAll(roleService.getUserGroupRoleIdsByUserId(user.getUserId()));
			userRoleBean.setRoleIds(roleIdList);
			userRoleBean.setVirRoleIds(virRoleIdList);
			userRoleBeanList.add(userRoleBean);
		}
		return userRoleBeanList;
	}

	/**
	 * 判断指定部门下是否有指定名称的部门
	 * @param parentId
	 * 
	 * @param name
	 * @return
	 */
	public boolean isHaveSameName(Integer parentId, String name) {
		
		return deptMapper.selectByParentIdAndDeptName(parentId,name).size() > 0;
	}

	/**
	 * 获取指定项目所在项目组的人员
	 * 
	 * @param proId
	 * @return
	 */
	public List<User> findVirDeptUser(Integer proId) {
		List<User> users = new ArrayList<>();
		List<Integer> virDeptIds = deptProjectMapper.selectDeptIdByProId(proId);
		if(virDeptIds.isEmpty()) {
			return users;
		}
		Integer proGroupId = virDeptIds.get(0);
		users = deptUserMapper.selectUserListByDeptId(proGroupId, null);
		return users;
	}
	
	/**
	 * 获取指定项目部的角色为施工单位人员
	 * 
	 * @param proId
	 * @return
	 */
	public List<User> findVirDeptExeUser(Integer proId) {
		List<User> users = new ArrayList<>();
		List<Integer> virDeptIds = deptProjectMapper.selectDeptIdByProId(proId);
		if(virDeptIds.isEmpty()) {
			return users;
		}
		Integer proGroupId = virDeptIds.get(0);
		users = userMapper.selectByDeptIdAndRoleName(proGroupId,"施工单位");
		return users;
	}
	

	/**
	 * 校验父级id是否合法
	 * 
	 * @param req
	 * @return
	 */
	public boolean checkParentId(ReqDept req) {
		if(req.getDeptId().equals(req.getParentId())) {
			return false;
		}
		return true;
	}

}
